package com.mmall.service.impl;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.mmall.common.RequestHolder;
import com.mmall.dao.SysDeptMapper;
import com.mmall.dao.SysUserMapper;
import com.mmall.exception.ParamException;
import com.mmall.param.DeptParm;
import com.mmall.pojo.SysDept;
import com.mmall.service.ISysDeptService;
import com.mmall.service.ISysLogService;
import com.mmall.util.BeanValidatorUtil;
import com.mmall.util.IpUtil;
import com.mmall.util.LevelUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @Author wangtengyu
 * @Create 2018-03-07-10:01
 */
@Service("iSysDeptService")
public class SysDeptServiceImpl implements ISysDeptService {


    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private ISysLogService iSysLogService;

    /**
     * 保存
     *
     * @param deptParm
     * @return
     */
    @Override
    public void save(DeptParm deptParm) {
        BeanValidatorUtil.check(deptParm);
        if (checkExist(deptParm.getParentId(), deptParm.getName(), deptParm.getId())) {
            throw new ParamException("同一层级下存在相同名称的部门");
        }
        SysDept sysDept = SysDept.builder().name(deptParm.getName()).parentId(deptParm.getParentId()).
                seq(deptParm.getSeq()).remark(deptParm.getRemark()).build();
        sysDept.setLevel(LevelUtil.getLevel(getLevel(deptParm.getParentId()), deptParm.getParentId()));
        sysDept.setOperator("system");
        sysDept.setOperateIp("127.0.0.1");
        sysDept.setOperateTime(new Date());
        sysDeptMapper.insertSelective(sysDept);
        iSysLogService.saveDeptLog(null,sysDept);
    }

    /**
     * 更新
     * @param deptParm
     */
    public void update(DeptParm deptParm) {
        BeanValidatorUtil.check(deptParm);
        if (checkExist(deptParm.getParentId(), deptParm.getName(), deptParm.getId())) {
            throw new ParamException("同一层级下存在相同名称的部门");
        }
        SysDept before = sysDeptMapper.selectByPrimaryKey(deptParm.getId());
        Preconditions.checkNotNull(before, "待更新的部门不存在");

        List<Integer> subIdList= Lists.newArrayList();
        getSubIdList(deptParm.getId(),subIdList);
        if(subIdList.contains(deptParm.getParentId())){
            throw new ParamException("上级部门不能为当前部门的子部门");
        }

        SysDept after = SysDept.builder().id(deptParm.getId()).name(deptParm.getName()).parentId(deptParm.getParentId()).
                seq(deptParm.getSeq()).remark(deptParm.getRemark()).build();
        after.setLevel(LevelUtil.getLevel(getLevel(deptParm.getParentId()), deptParm.getParentId()));
        after.setOperator(RequestHolder.getCurrentUser().getUsername());
        after.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
        after.setOperateTime(new Date());
        updateWithChild(before,after);
        iSysLogService.saveDeptLog(before,after);
    }

    /**
     * 删除
     * @param deptId
     */
    public void delete(int deptId){
        SysDept dept=sysDeptMapper.selectByPrimaryKey(deptId);
        Preconditions.checkNotNull(dept,"要删除的部门不存在，无法删除");
        if(sysDeptMapper.countByParentId(dept.getId())>0){
            throw new ParamException("当前部门下有子部门,无法删除");
        }
        if(sysUserMapper.countByDeptId(dept.getId())>0){
            throw new ParamException("当前部门下有用户,无法删除");
        }
        sysDeptMapper.deleteByPrimaryKey(deptId);
        iSysLogService.saveDeptLog(dept,null);
    }


    /**
     * 更新->子节点更新
     * @param before
     * @param after
     */
    @Transactional
    public void updateWithChild(SysDept before, SysDept after) {
        String oldLevelPrefix = before.getLevel();
        String newLevelPrefix = after.getLevel();
        if (!oldLevelPrefix.equals(newLevelPrefix)) {
            List<SysDept> deptList = sysDeptMapper.getChildDeptListByLevel(before.getLevel()+"."+before.getId());
            if (CollectionUtils.isNotEmpty(deptList)) {
                for (SysDept dept : deptList) {
                    String level = dept.getLevel();
                    if (level.indexOf(oldLevelPrefix) == 0){
                        level=newLevelPrefix+level.substring(oldLevelPrefix.length());//索引是从0开始的，假设长度是5,这就是从6开始
                        dept.setLevel(level);
                    }
                }
                sysDeptMapper.batchUpdateLevel(deptList);
            }
        }
        sysDeptMapper.updateByPrimaryKey(after);

    }

    /**
     * 检查是否同一部门层级下还存在另一层级
     *
     * @param parentId
     * @param deptName
     * @param deptId
     * @return
     */
    private boolean checkExist(Integer parentId, String deptName, Integer deptId) {
        return sysDeptMapper.countByNameAndParentIdAndId(parentId, deptName, deptId) > 0;
    }


    /**
     * 获取部门所在层级level
     * @param deptId
     * @return
     */
    private String getLevel(Integer deptId) {
        SysDept dept = sysDeptMapper.selectByPrimaryKey(deptId);
        if (dept == null) {
            return null;
        }
        return dept.getLevel();
    }


    /**
     * 递归获得当前选择模块的子模块的id集合
     * @param parentId
     * @param subIdList
     */
    private void getSubIdList(Integer parentId,List<Integer> subIdList){
        List<SysDept> sysDeptList=sysDeptMapper.selectByParentId(parentId);
        if(CollectionUtils.isNotEmpty(sysDeptList)){
            for(SysDept sysDept:sysDeptList){
                subIdList.add(sysDept.getId());
                getSubIdList(sysDept.getId(),subIdList);
            }
        }
    }

}
